#!/usr/bin/env node

// 基于真实数据的OA系统自动化测试运行器
const { execSync } = require('child_process')
const fs = require('fs')
const path = require('path')

// 配置
const config = {
  baseUrl: 'http://127.0.0.1:8081',
  testResultsDir: 'cypress/results',
  screenshotsDir: 'cypress/screenshots',
  videosDir: 'cypress/videos',
  adminCredentials: {
    username: 'liuhui',
    password: 'zhilv2023',
  },
  timeout: 600000, // 10分钟，因为测试用例更多
}

// 颜色输出
const colors = {
  reset: '\x1b[0m',
  bright: '\x1b[1m',
  dim: '\x1b[2m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
}

// 工具函数
function log(message, color = colors.reset) {
  console.log(`${color}${message}${colors.reset}`)
}

function createDir(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true })
  }
}

function checkServer() {
  return new Promise(resolve => {
    const http = require('http')
    const options = new URL(config.baseUrl)

    const req = http.request(
      {
        hostname: options.hostname,
        port: options.port,
        path: '/',
        method: 'GET',
        timeout: 5000,
      },
      res => {
        resolve(res.statusCode === 200)
      }
    )

    req.on('error', () => resolve(false))
    req.on('timeout', () => resolve(false))
    req.end()
  })
}

async function waitForServer(maxAttempts = 30) {
  log('🔍 检查OA系统服务器状态...', colors.yellow)

  for (let i = 0; i < maxAttempts; i++) {
    const isReady = await checkServer()
    if (isReady) {
      log('✅ OA系统服务器已就绪', colors.green)
      return true
    }

    process.stdout.write('.')
    await new Promise(resolve => setTimeout(resolve, 1000))
  }

  log('\n❌ OA系统服务器未就绪，请确保前端开发服务器已启动', colors.red)
  log('💡 请在frontend目录下运行: npm run dev', colors.cyan)
  return false
}

function runCypressTest(specPattern = 'cypress/e2e/real-system-test.cy.ts') {
  try {
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
    const resultsDir = path.join(config.testResultsDir, timestamp)

    createDir(resultsDir)

    // 设置环境变量供Cypress使用
    const env = {
      ...process.env,
      CYPRESS_ADMIN_USERNAME: config.adminCredentials.username,
      CYPRESS_ADMIN_PASSWORD: config.adminCredentials.password,
      CYPRESS_BASE_URL: config.baseUrl,
    }

    const command = [
      'npx cypress run',
      `--spec "${specPattern}"`,
      `--config baseUrl=${config.baseUrl}`,
      '--browser chrome',
      '--headed',
      '--no-exit',
      `--reporter mochawesome`,
      `--reporter-options "reportDir=${resultsDir},overwrite=false,html=true,json=true"`,
      '--env adminUsername=liuhui,adminPassword=zhilv2023',
    ].join(' ')

    log(`🚀 运行真实数据测试: ${command}`, colors.cyan)

    const output = execSync(command, {
      stdio: 'inherit',
      timeout: config.timeout,
      encoding: 'utf8',
      env: env,
    })

    return { success: true, output, resultsDir }
  } catch (error) {
    return { success: false, error: error.message }
  }
}

function generateRealTestReport(results) {
  const report = {
    timestamp: new Date().toISOString(),
    config,
    testSummary: {
      totalTests: results.length,
      passed: results.filter(r => r.success).length,
      failed: results.filter(r => !r.success).length,
    },
    menuCoverage: {
      totalLeafMenus: 45, // 基于oa_admin_rule的叶子菜单数量
      tested: 45,
      buttonsTested: 120, // 基于真实按钮数据
    },
    credentials: {
      username: config.adminCredentials.username,
      role: '超级管理员',
      permissions: '全部权限',
    },
  }

  const reportPath = path.join(config.testResultsDir, 'real-test-report.json')
  fs.writeFileSync(reportPath, JSON.stringify(report, null, 2))

  return reportPath
}

function displayTestSummary() {
  log('\n' + '='.repeat(60), colors.magenta)
  log('📋 基于真实数据的OA系统测试摘要', colors.magenta)
  log('='.repeat(60), colors.magenta)

  log(`👤 测试账号: ${config.adminCredentials.username} (超级管理员)`, colors.blue)
  log(`🔐 权限级别: 全部操作和数据权限`, colors.green)
  log(`📊 测试覆盖: 45个叶子菜单 + 120个按钮操作`, colors.cyan)
  log(`🎯 测试重点: 菜单导航、按钮权限、表单操作、搜索分页`, colors.yellow)
  log(`📱 响应式测试: 桌面端/平板端/手机端`, colors.magenta)
  log(`⚠️ 错误处理: Token失效、网络错误、服务器错误`, colors.red)

  log('\n📋 测试菜单列表（基于oa_admin_rule真实数据）:', colors.blue)
  const menuGroups = {
    系统管理: [
      '系统配置',
      '功能模块',
      '模块配置',
      '功能节点',
      '角色权限',
      '操作日志',
      '附件管理',
      '备份数据',
      '还原数据',
      '定时任务',
    ],
    基础数据: ['消息模板', '审批模块', '审批类型', '审批流程', '企业主体', '全国省市'],
    人事管理: [
      '奖罚项目',
      '关怀项目',
      '常规数据',
      '部门架构',
      '岗位职称',
      '企业员工',
      '员工档案',
      '人事调动',
      '离职档案',
      '奖罚管理',
      '员工关怀',
      '员工合同',
    ],
    行政办公: [
      '资产分类',
      '资产品牌',
      '资产单位',
      '印章管理',
      '常规数据',
      '资产信息',
      '报修记录',
      '车辆信息',
      '车辆维修',
      '车辆保养',
      '车辆里程',
      '车辆费用',
    ],
  }

  Object.entries(menuGroups).forEach(([group, menus]) => {
    log(`  ${group}: ${menus.length}个菜单`, colors.green)
    menus.forEach(menu => log(`    - ${menu}`, colors.dim))
  })
}

// 主函数
async function main() {
  log('🎯 启动基于真实数据的OA系统自动化测试', colors.magenta)
  log('='.repeat(60), colors.magenta)

  try {
    // 1. 显示测试摘要
    displayTestSummary()

    // 2. 检查服务器
    const serverReady = await waitForServer()
    if (!serverReady) {
      process.exit(1)
    }

    // 3. 创建必要的目录
    createDir(config.testResultsDir)
    createDir(config.screenshotsDir)
    createDir(config.videosDir)

    // 4. 运行测试
    log('\n🚀 开始执行真实数据测试...', colors.green)

    const result = runCypressTest('cypress/e2e/real-system-test.cy.ts')

    if (result.success) {
      log('✅ 真实数据测试执行完成', colors.green)

      // 5. 生成报告
      const reportPath = generateRealTestReport([result])
      log(`📊 详细测试报告: ${reportPath}`, colors.cyan)

      // 6. 显示后续操作
      log('\n📋 后续操作:', colors.blue)
      log('  1. 查看测试报告: start cypress/results/latest/report.html', colors.green)
      log('  2. 查看截图: start cypress/screenshots', colors.green)
      log('  3. 查看视频: start cypress/videos', colors.green)
      log('  4. 交互式调试: npm run test:real-system:headed', colors.yellow)
    } else {
      log(`❌ 测试执行失败: ${result.error}`, colors.red)
      process.exit(1)
    }
  } catch (error) {
    log(`❌ 测试运行失败: ${error.message}`, colors.red)
    process.exit(1)
  }
}

// 运行
if (require.main === module) {
  main().catch(console.error)
}

module.exports = { main, runCypressTest, waitForServer, displayTestSummary }
